package ar.edu.unq.wannaplay.helpers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ar.edu.unq.wannaplay.entity.Entity;
import ar.edu.unq.wannaplay.ocupation.CareerPlan;
import ar.edu.unq.wannaplay.ocupation.Percentages;
import ar.edu.unq.wannaplay.utils.Pair;

public class CareerPlanOrganizer extends Entity {

    private static final long serialVersionUID = 1L;

    private Map<String, Percentages> ranks;

    private List<CareerPlan> careerPlans;

    private List<String> orderedRanks;

    public CareerPlanOrganizer() {
        super();
        ranks = new HashMap<String, Percentages>();
        careerPlans = new ArrayList<CareerPlan>();
        orderedRanks = new ArrayList<String>();
    }

    public CareerPlan createCarrerPlan(final String name) {
        CareerPlan plan = new CareerPlan(name);
        this.getCareerPlans().add(plan);
        this.addRanks(plan);
        return plan;
    }

    public void addNewRank(final String rankName, final Percentages range, final int order) {
        ranks.put(rankName, range);
        this.addRanksInCareers(rankName);
        if (!this.getSortedRanks().contains(rankName)) {
            this.getSortedRanks().add(order, rankName);
        }
    }

    private void addRanksInCareers(final String rankName) {
        for (CareerPlan currentCareer : this.getCareerPlans()) {
            currentCareer.addSalaries(rankName, Pair.defaultPair());
        }
    }

    public int highestRange() {
        return this.getSortedRanks().size();
    }

    public boolean hasNextRange(final String rank) {
        return this.getSortedRanks().indexOf(rank) < this.highestRange() - 1;
    }

    public boolean hasPreviousRange(final String rank) {
        return this.getSortedRanks().indexOf(rank) > 0;
    }

    public String nextRange(final String rank) {
        return this.getSortedRanks().get(this.getSortedRanks().indexOf(rank) + 1);
    }

    public String previousRange(final String rank) {
        return this.getSortedRanks().get(this.getSortedRanks().indexOf(rank) - 1);
    }

    public int getOrder(final String rank) {
        return this.getSortedRanks().indexOf(rank);
    }

    public void modifyRank(final String rank, final Percentages range) {
        this.addNewRank(rank, range, this.getOrder(rank));
    }

    public void removeRank(final String rank) {
        if (ranks.containsKey(rank)) {
            ranks.remove(rank);
        }
        this.removeRanksInCareers(rank);
        this.getSortedRanks().remove(rank);
    }

    private void removeRanksInCareers(final String rank) {
        for (CareerPlan careerPlan : this.getCareerPlans()) {
            if (careerPlan.hasRank(rank)) {
                careerPlan.removeRank(rank);
            }
        }
    }

    public List<String> getRankNames() {
        return new ArrayList<String>(ranks.keySet());
    }

    public Map<String, Percentages> getMapRanks() {
        return ranks;
    }

    public void addNewRank(final String rankName, final Percentages range) {
        this.addNewRank(rankName, range, this.highestRange());
    }

    public Percentages getRange(final String rangeName) {
        return ranks.get(rangeName);
    }

    public List<CareerPlan> getCareerPlans() {
        return careerPlans;
    }

    private void addRanks(final CareerPlan careerPlan) {
        for (String currentRank : ranks.keySet()) {
            careerPlan.addSalaries(currentRank, Pair.defaultPair());
        }
    }

    public Percentages buildRange(final Integer... range) {
        Percentages ranges = new Percentages();
        for (Integer element : range) {
            ranges.add(element);
        }
        return ranges;

    }

    public void modifyRankName(final String oldRankName, final String newRankName) {
        Percentages ranges = ranks.remove(oldRankName);
        ranks.put(newRankName, ranges);
        for (CareerPlan careerPlan : this.getCareerPlans()) {
            careerPlan.modifyRankName(oldRankName, newRankName);
        }
        this.swapRanks(oldRankName, newRankName);

    }

    private void swapRanks(final String oldRankName, final String newRankName) {
        int index = this.getSortedRanks().indexOf(oldRankName);
        this.getSortedRanks().add(index, newRankName);
        this.getSortedRanks().remove(oldRankName);
    }

    public List<String> getSortedRanks() {
        return orderedRanks;
    }

    public void modifySalaries(final String careerPlanName, final String rankName, final int base, final int max) {
        this.findCareerPlanByName(careerPlanName).modifySalaries(rankName, base, max);
    }

    public void addSalaries(final String careerPlanName, final String rankName, final int base, final int max) {
        this.findCareerPlanByName(careerPlanName).addSalaries(rankName, base, max);
    }

    private CareerPlan findCareerPlanByName(final String name) {
        CareerPlan careerPlan = null;
        for (CareerPlan currentPlan : this.getCareerPlans()) {
            if (currentPlan.getName().equals(name)) {
                careerPlan = currentPlan;
            }
        }
        return careerPlan;
    }

    public void removeCareerPlan(final String name) {
        boolean found = false;
        int index = 0;
        while (!found || index == this.getCareerPlans().size()) {
            if (this.getCareerPlans().get(index).getName().equals(name)) {
                found = true;
                this.getCareerPlans().remove(index);
            }
            index++;
        }
    }

    public void modifySalaries(final String name, final Map<String, Pair<Integer, Integer>> salaries) {
        this.findCareerPlanByName(name).setSalaries(salaries);
    }

    public void modifyCareerPlanName(final String oldName, final String newName) {
        this.findCareerPlanByName(oldName).setName(newName);
    }

    public List<String> getOrderedRanks() {
        return orderedRanks;
    }

    public void setOrderedRanks(final List<String> orderedRanks) {
        this.orderedRanks = orderedRanks;
    }

    public void setRanks(final Map<String, Percentages> ranks) {
        this.ranks = ranks;
    }

    public void setCareerPlans(final List<CareerPlan> careerPlans) {
        this.careerPlans = careerPlans;
    }

    public Map<String, Percentages> getRanks() {
        return ranks;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || !(obj instanceof CareerPlanOrganizer)) {
            return false;
        }

        CareerPlanOrganizer other = (CareerPlanOrganizer) obj;

        if (this.getId() == other.getId()) {
            return true;
        }
        if ((Integer) this.getId() == null) {
            return false;
        }

        // equivalence by id
        return ((Integer) this.getId()).equals(other.getId());
    }

    @Override
    public int hashCode() {
        if ((Integer) this.getId() != null) {
            return ((Integer) this.getId()).hashCode();
        } else {
            return super.hashCode();
        }
    }

}
